import numpy as np
import cv2,math
def guideFilter(I, p, winSize, eps):
    """
    导向图像(Guidance Image) I，滤波输出图像(Filtering Input Image) p，均值平滑窗口半径 r，正则化参数 e。
    利用导向滤波进行图像平滑处理时，通常令p=I。
    其中：guideFilter(）函数调用opencv自带的库函数blur() 进行均值平滑。
    :param I:
    :param p:
    :param winSize:
    :param eps:
    :return:
    """
    
    sqaure_avg = cv2.blur(p * p, winSize)
    avg = cv2.blur(p, winSize)
    
    ak = (sqaure_avg - avg ** 2)/(sqaure_avg - avg **2 + eps)
    bk = (-1 * ak + 1) * avg
    
    a = cv2.blur(ak, winSize)
    b = cv2.blur(bk, winSize)
    
    q = a * p + b
    
    return q

 


def fastGuideFilter(I, p, winSize, eps, s):
    """
    导向图像(Guidance Image) I，滤波输出图像(Filtering Input Image) p，正则化参数 eps。
    利用导向滤波进行图像平滑处理时，通常令p=I。
    其中：guideFilter(）函数调用opencv自带的库函数blur() 进行均值平滑。
    :param I:
    :param p:
    :param winSize:
    :param eps:
    :return:
    """
    
    sp = cv2.resize(p, None, fx=s, fy=s) #和经典导向滤波差不多，就是多了一个缩放图的过程
    
    
    sqaure_avg = cv2.blur(sp * sp, winSize)
    avg = cv2.blur(sp, winSize)
    
    ak = (sqaure_avg - avg ** 2)/(sqaure_avg - avg **2 + eps)
    bk = (-1 * ak + 1) * avg
    
    a = cv2.blur(ak, winSize)
    b = cv2.blur(bk, winSize)
    
    bigA = cv2.resize(a, None, fx=1/s, fy=1/s)
    bigB = cv2.resize(b, None, fx=1/s, fy=1/s) 
    q = bigA * p + bigB
    
    return q

"""
下图导向滤波采用了r=16也就是winSize=(16,16), eps=0.01的参数大小。  
快速导向滤波采用了r=16也就是winSize=(16,16), eps=0.01，s=0.5的参数大小。
"""
def run():
    name = input("Please input the file name\n")
    image = cv2.imread(name, cv2.IMREAD_ANYCOLOR)
    #将图像归一化
    
    # time start
    t1 = cv2.getTickCount()
    image_0_1 = image/255.0
 
    #导向滤波(三通道)
    b, g, r = cv2.split(image_0_1)
    gf1 = guideFilter(b, b, (16,16), math.pow(0.1,2))
    gf2 = guideFilter(g, g, (16,16), math.pow(0.1,2))
    gf3 = guideFilter(r, r, (16,16), math.pow(0.1,2))

#     gf1 = FastguideFilter(b, b, (16, 16), math.pow(0.1, 2),s=0.5)
#     gf2 = FastguideFilter(g, g, (16, 16), math.pow(0.1, 2),s=0.5)
#     gf3 = FastguideFilter(r, r, (16, 16), math.pow(0.1, 2),s=0.5)
    gf = cv2.merge([gf1, gf2, gf3])
 
    print(gf.shape)
 
    
    
    

    #保存导向滤波结果
    gf = gf*255
    gf[gf>255] = 255
    gf = np.round(gf)
    gf = gf.astype(np.uint8)
    res = np.hstack((image,gf))
    
    # time end
    t2 = cv2.getTickCount()
 
    # 计算执行秒数,利用getTickFrequency()获取时钟频率
    t = (t2 - t1) / cv2.getTickFrequency()
    print(t)
    
    cv2.imshow("res",res)
    cv2.waitKey(0)
    return gf




gf = run()
 
 